home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / GraphicViewers / ViewGif2 / Source / Animator.old.m < prev    next >
Text File  |  1991-07-17  |  4KB  |  179 lines

  1.  
  2. /*
  3.  *  An 'Animator' controls the timing for your action method of choice.
  4.  *  The object may function as a general timer object; i.e.
  5.  *  graphics are neither expected nor required by the class.
  6.  *  When you create an Animator with +newChronon, you specify
  7.  *  the time interval between calls, the adaptation time constant (see below),
  8.  *  the target to which the method belongs, the action name, whether to 
  9.  *  automatically start up the timing upon creation, and an event mask (if you     
  10.  *  plan to break conditionally out of loops within the action method.
  11.  *
  12.  *  The Animator has adaptive means for adjusting to harsh operating
  13.  *  environments.  An adaptation constant d > 0. will invoke dynamical 
  14.  *  correction of entry times, on-the-fly, so that the desired chronon
  15.  *  will be realized in a real-time sense.
  16.  *
  17.  *  Functionality and applications are discussed in Report ETC-0008.
  18.  */
  19.  
  20. #import "Animator.h"
  21.  
  22. #import <appkit/Application.h>
  23. #import <sys/time.h>
  24. #import <objc/vectors.h>
  25.  
  26. @implementation Animator
  27.  
  28. void TimerFunc(teNum,now,self)
  29. DPSTimedEntry teNum;
  30. double now;
  31. id self;
  32. {
  33.   struct timezone tzone;
  34.  
  35.   gettimeofday(&self->entrytime,&tzone);
  36.   if(self->howOften > 0.) [self adapt];
  37.   [self->target perform:self->action with:self];
  38. }
  39.  
  40. + newChronon: (double) dt    /* The time increment desired. */
  41.     adaptation:(double)howoft  /* Adaptive time constant (0.deactivates).*/
  42.     target: (id) targ    /* Target to whom proc belongs. */
  43.     action: (SEL) act    /* The action. */
  44.     autoStart: (int) start    /* Automatic start of timed entry? */
  45.     eventMask: (int) eMask  /* Mask for optional check in "shouldBreak". */
  46. {
  47.   self = [super new];
  48.   ticking = NO;
  49.   desireddt = dt;
  50.   [self setIncrement: dt];
  51.   [self setAdaptation: howoft];
  52.   [self setTarget: targ];
  53.   [self setAction: act];
  54.   if(start) [self startEntry];
  55.   mask = eMask;
  56.   [self resetRealTime];
  57.   return self;
  58. }
  59.  
  60. - resetRealTime { 
  61. /* After this call, getDoubleRealTime is the real time that ensues. */
  62.     struct timeval realtime;
  63.         struct timezone tzone;
  64.  
  65.     gettimeofday(&realtime,&tzone);
  66.     synctime = realtime.tv_sec + realtime.tv_usec/1000000.0;
  67.     passcounter = 0;
  68.     t0 = 0.0;
  69.     return self;
  70. }
  71.  
  72. - (double) getSyncTime {
  73.     return(synctime);
  74. }
  75.  
  76. - (double) getDoubleEntryTime {
  77. /* Returns real time since "resetrealTime". */
  78.     return(- synctime + entrytime.tv_sec + entrytime.tv_usec/1000000.0);
  79. }
  80.  
  81. - (double) getDoubleRealTime {
  82. /* Returns real time since "resetrealTime". */
  83.     struct timeval realtime;
  84.     struct timezone tzone;
  85.  
  86.     gettimeofday(&realtime,&tzone);
  87.     return(- synctime + realtime.tv_sec + realtime.tv_usec/1000000.0);
  88. }
  89.  
  90. - (double) getDouble {
  91.     return([self getDoubleRealTime]);
  92. }
  93.  
  94. - adapt {
  95. /* Adaptive time-step algorithm. */
  96.   double t;
  97.   if(!ticking) return self;
  98.   ++passcounter;
  99.   t = [self getDoubleEntryTime];
  100.   if(t - t0 >= howOften) {      
  101.       adapteddt *= desireddt*passcounter/(t - t0);
  102.     [self setIncrement: adapteddt];
  103.     [self startEntry];
  104.     passcounter = 0;
  105.     t0 = t;
  106.   }
  107.   return self;
  108. }
  109.   
  110. - setBreakMask : (int) eventMask {
  111.   mask = eventMask;
  112.   return self;
  113. }
  114.  
  115. - (int) getBreakMask {
  116.   return(mask);
  117. }
  118.  
  119. - (int) isTicking {
  120.   return(ticking);
  121. }
  122.    
  123. - (int) shouldBreak  {
  124. /* Call this to see if you want to exit a loop in your action method. */
  125.    int   found;
  126.    NXEvent *e, event;
  127.    e = [NXApp peekNextEvent:mask into:&event 
  128.           waitFor:0.0 threshold:NX_BASETHRESHOLD];
  129.    return(e ? 1: 0);
  130. }
  131.  
  132. - setIncrement: (double) dt {
  133.   adapteddt = dt;
  134.   interval = dt;
  135.   return self;
  136. }
  137.  
  138. - (double) getIncrement {
  139.   return(adapteddt);
  140. }
  141.  
  142. - setAdaptation: (double) oft {
  143.   howOften = oft;
  144.   return self;
  145. }
  146.  
  147. - setTarget: (id) targ {
  148.   target = targ;
  149. }
  150.  
  151. - setAction:(SEL) aSelector
  152. {
  153.     action = 
  154.     aSelector && !ISSELECTOR(aSelector) ? (*_cvtToSel) (aSelector) : aSelector;
  155.     return self;
  156. }
  157.  
  158. - startEntry
  159.   [self stopEntry];
  160.   teNum = DPSAddTimedEntry(interval,&TimerFunc,self,NX_BASETHRESHOLD);
  161.   ticking = YES;
  162.   return self;
  163. }
  164.  
  165. - stopEntry
  166. {
  167.   if (ticking) DPSRemoveTimedEntry(teNum);
  168.   ticking = NO;
  169.   return self;
  170. }
  171.  
  172. - free
  173. {
  174.   if (ticking) DPSRemoveTimedEntry(teNum);
  175.   return [super free];
  176. }
  177. @end    
  178.